package cn.boltzjf.sql4j;

import java.util.Objects;

public class Column<T> implements Comparable<Column<?>> {
    
    public static abstract class Type implements Comparable<Type> {
        
        public abstract String name();
        
        @Override
        public int hashCode() {
            return Objects.hash(name());
        }
        
        @Override
        public boolean equals(Object o) {
            return this == o || o != null && Type.class.equals(o.getClass()) && this.name().equals(Type.class.cast(o).name());
        }
        
        @Override
        public int compareTo(Type o) {
            return o != null ? name().compareTo(o.name()) : 1;
        }
        
        @Override
        public String toString() {
            return name();
        }
        
    }
    
    private final String name;
    private final Type type;
    private final Class<T> javaType;

    public Column(String name, Type type, Class<T> javaType) {
        notNull(name, "Name should not be null");
        notNull(type, "Column Type should not be null");
        notNull(javaType, "Java Type should not be null");
        this.name = name;
        this.type = type;
        this.javaType = javaType;
    }
    
    public String name() {
        return name;
    }
    
    public Class<T> javaType() {
        return javaType;
    }
    
    public Type type() {
        return type;
    }
    
    @Override
    public String toString() {
        return name;
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(name, type, javaType);
    }
    
    @Override
    public boolean equals(Object other) {
        return other == null ? false
                : this == other ? true
                        : this.getClass().equals(other.getClass())
                            && Objects.equals(name, ((Column<?>)other).name)
                            && Objects.equals(type, ((Column<?>)other).type)
                            && Objects.equals(javaType, ((Column<?>)other).javaType);
    }

    @Override
    public int compareTo(Column<?> o) {
        int r = name.compareTo(o.name);
        if (r != 0) {
            return r;
        }
        r = type.compareTo(o.type);
        if (r != 0) {
            return r;
        }
        return  javaType.getName().compareTo(o.javaType.getName());
    }
    
    private void notNull(Object obj, String msg) {
        if (obj == null) {
            throw new IllegalArgumentException(msg);
        }
    }
}
